﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace Bikiball.XLoader
{
    public enum LexerContext
    {
        String,
        Int,
        Float,
        Char,
    }
    public class Lexer
    {
        private Token _token;
        private int _tokenNumber = 0;
        private List<Token> _tokens;

        public Token Token
        {
            get
            {
                return _token;
            }
        }
        public Lexer(String FilePath)
        {
            StreamReader streamReader = new StreamReader(FilePath);
            String buffer = streamReader.ReadToEnd();
            Regex regex = new Regex(@"(?<string>[a-zA-Z_$][a-zA-Z0-9_$]*)|" +
                                    @"(?<float>-?[0-9]+\.[0-9]+)|" +
                                    @"(?<integer>-?[0-9]+)|" +
                                    @"(?<plus>\+)|" +
                                    @"(?<minus>-)|" +
                                    @"(?<multiply>\*)|" +
                                    @"(?<obrace>{)|" +
                                    @"(?<cbrace>})|" +
                                    @"(?<oparen>\()|" +
                                    @"(?<cparen>\))|" +
                                    @"(?<obracket>\[)|" +
                                    @"(?<comma>,)|" +
                                    @"(?<semicolon>;)|" +
                                    @"(?<cbracket>\])");
            MatchCollection matches = regex.Matches(buffer);
            _tokens = new List<Token>();
            try
            {
            foreach (Match match in matches)
            {
                int i = 0;

                    foreach (Group group in match.Groups)
                    {
                        string matchValue = group.Value;
                        bool success = group.Success;
                        // ignore capture index 0 and 1 (general and WhiteSpace)
                        if (success && i >= 1)
                        {
                            string groupName = regex.GroupNameFromNumber(i);
                            Token token = new Token();
                            token.SetValue<String>(matchValue);
#warning Stupid
                            switch (groupName)
                            {
                                case "string":
                                    token.Type = TokenType.String;
                                    break;
                                case "float":
                                    token.Type = TokenType.Float;
                                    break;
                                case "obrace":
                                    token.Type = TokenType.OBrace;
                                    break;
                                case "cbrace":
                                    token.Type = TokenType.CBrace;
                                    break;
                                case "oparen":
                                    token.Type = TokenType.OParen;
                                    break;
                                case "cparen":
                                    token.Type = TokenType.CParen;
                                    break;
                                case "cbracket":
                                    token.Type = TokenType.CBracket;
                                    break;
                                case "obracket":
                                    token.Type = TokenType.OBracket;
                                    break;
                                case "comma":
                                    token.Type = TokenType.Comma;
                                    break;
                                case "semicolon":
                                    token.Type = TokenType.Semicolon;
                                    break;
                                case "integer":
                                    token.Type = TokenType.Integer;
                                    break;
                                default:
                                    throw new Exception("[Invalid Token] Value : " + matchValue + " Type : " + groupName);
                                    break;
                            }
                            _tokens.Add(token);
                        }
                        i++;
                    }
                }
            }
            catch (Exception e)
            {
                Debug.WriteLine(e);
            }
        }

        public Token GetToken(LexerContext context)
        {
            if (_tokens.Count < _tokenNumber)
                return _tokens[_tokenNumber];
            return new Token() { Type = TokenType.EOF };
        }
    }
}
